package com.personalink.management.service;

import com.personalink.common.entity.PersonaConfig;
import com.personalink.common.exception.BusinessException;
import com.personalink.management.dto.PersonaSwitchRequest;
import com.personalink.management.dto.PersonaSwitchResponse;
import com.personalink.management.repository.PersonaRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 人格管理服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PersonaService {
    
    private final PersonaRepository personaRepository;
    private final RedisTemplate<String, Object> redisTemplate;
    private final CooldownService cooldownService;
    
    @Value("${persona.cooldown.persona-switch:30}")
    private Integer defaultCooldownSeconds;
    
    private static final String USER_PERSONA_KEY = "user:persona:";
    private static final String USER_CONFIG_KEY = "user:config:";
    
    /**
     * 获取所有可用人格
     */
    public List<PersonaConfig> getAllPersonas() {
        return personaRepository.findByEnabledTrue();
    }
    
    /**
     * 根据ID获取人格
     */
    public PersonaConfig getPersonaById(String personaId) {
        return personaRepository.findById(personaId)
                .orElseThrow(() -> new BusinessException("人格不存在: " + personaId));
    }
    
    /**
     * 切换人格
     */
    public PersonaSwitchResponse switchPersona(PersonaSwitchRequest request) {
        String userId = request.getUserId();
        String targetPersonaId = request.getPersonaId();
        
        // 1. 验证目标人格是否存在且可用
        PersonaConfig targetPersona = getPersonaById(targetPersonaId);
        if (!targetPersona.getEnabled()) {
            throw new BusinessException("人格已禁用: " + targetPersonaId);
        }
        
        // 2. 获取当前人格
        String currentPersonaId = getCurrentPersonaId(userId);
        
        // 3. 检查是否需要切换
        if (targetPersonaId.equals(currentPersonaId)) {
            throw new BusinessException("已经是当前人格，无需切换");
        }
        
        // 4. 检查冷却时间（除非强制切换）
        if (!request.getForceSwitch() && !cooldownService.canSwitch(userId)) {
            long remainingTime = cooldownService.getRemainingCooldown(userId);
            throw new BusinessException(429, 
                    String.format("人格切换冷却中，请等待 %d 秒后重试", remainingTime));
        }
        
        // 5. 执行切换
        LocalDateTime switchTime = LocalDateTime.now();
        setCurrentPersona(userId, targetPersonaId);
        
        // 6. 设置冷却时间
        cooldownService.setCooldown(userId, defaultCooldownSeconds);
        
        // 7. 记录切换历史
        recordPersonaSwitch(userId, currentPersonaId, targetPersonaId, switchTime);
        
        // 8. 构建响应
        return PersonaSwitchResponse.builder()
                .previousPersona(currentPersonaId)
                .currentPersona(targetPersonaId)
                .cooldown(defaultCooldownSeconds)
                .cooldownEndTime(switchTime.plusSeconds(defaultCooldownSeconds))
                .switchTime(switchTime)
                .firstSwitch(currentPersonaId == null)
                .personaName(targetPersona.getName())
                .personaDescription(targetPersona.getDescription())
                .build();
    }
    
    /**
     * 获取用户当前人格
     */
    public PersonaConfig getCurrentPersona(String userId) {
        String personaId = getCurrentPersonaId(userId);
        if (personaId == null) {
            // 返回默认人格（情感伴侣）
            return getPersonaById("companion");
        }
        return getPersonaById(personaId);
    }
    
    /**
     * 获取用户当前人格ID
     */
    public String getCurrentPersonaId(String userId) {
        return (String) redisTemplate.opsForValue().get(USER_PERSONA_KEY + userId);
    }
    
    /**
     * 设置用户当前人格
     */
    public void setCurrentPersona(String userId, String personaId) {
        redisTemplate.opsForValue().set(USER_PERSONA_KEY + userId, personaId);
    }
    
    /**
     * 更新人格配置
     */
    public void updatePersonaConfig(String userId, String personaId, Map<String, Object> config) {
        // 验证人格是否存在
        getPersonaById(personaId);
        
        String configKey = USER_CONFIG_KEY + userId + ":" + personaId;
        redisTemplate.opsForHash().putAll(configKey, config);
        
        log.info("用户 {} 更新人格 {} 配置: {}", userId, personaId, config);
    }
    
    /**
     * 获取人格配置
     */
    public Map<String, Object> getPersonaConfig(String userId, String personaId) {
        String configKey = USER_CONFIG_KEY + userId + ":" + personaId;
        Map<Object, Object> config = redisTemplate.opsForHash().entries(configKey);
        
        Map<String, Object> result = new HashMap<>();
        config.forEach((k, v) -> result.put(k.toString(), v));
        
        return result;
    }
    
    /**
     * 获取冷却状态
     */
    public Map<String, Object> getCooldownStatus(String userId) {
        Map<String, Object> status = new HashMap<>();
        status.put("canSwitch", cooldownService.canSwitch(userId));
        status.put("remainingTime", cooldownService.getRemainingCooldown(userId));
        status.put("currentPersona", getCurrentPersonaId(userId));
        
        return status;
    }
    
    /**
     * 重置人格状态
     */
    public void resetPersonaState(String userId) {
        // 清除当前人格
        redisTemplate.delete(USER_PERSONA_KEY + userId);
        
        // 清除冷却时间
        cooldownService.clearCooldown(userId);
        
        // 清除所有人格配置
        String pattern = USER_CONFIG_KEY + userId + ":*";
        redisTemplate.delete(redisTemplate.keys(pattern));
        
        log.info("重置用户 {} 人格状态", userId);
    }
    
    /**
     * 记录人格切换历史
     */
    private void recordPersonaSwitch(String userId, String fromPersona, String toPersona, LocalDateTime switchTime) {
        Map<String, Object> record = new HashMap<>();
        record.put("userId", userId);
        record.put("fromPersona", fromPersona);
        record.put("toPersona", toPersona);
        record.put("switchTime", switchTime.toString());
        
        String historyKey = "persona:switch:history:" + userId;
        redisTemplate.opsForList().leftPush(historyKey, record);
        
        // 只保留最近100条记录
        redisTemplate.opsForList().trim(historyKey, 0, 99);
        
        // 设置过期时间（30天）
        redisTemplate.expire(historyKey, 30, TimeUnit.DAYS);
    }
}